﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using ImageProcessing.Helper;
using AForge.Imaging;

namespace ImageProcessing
{
    class BackgroundCalculation
    {
        private int _width;
        private int _height;
        private int _imageCount = 0;

        private RGB[,] _background; 

        /// <summary>
        /// Class for calculating and eliminating background
        /// </summary>
        /// <param name="width">Image width</param>
        /// <param name="height">Image height</param>
        public BackgroundCalculation(int width, int height)
        {
            this._width = width;
            this._height = height;

            this._background = new RGB[width, height];
        }
        /// <summary>
        /// Class for calculating and eliminating background
        /// </summary>
        /// <param name="size">Image size</param>
        public BackgroundCalculation(Size size) : this(size.Width, size.Height) { }


        /// <summary>
        /// Removes current background-information
        /// </summary>
        public void Clear()
        {
            _imageCount = 0;
            _background = new RGB[_width, _height];
        }

        /// <summary>
        /// Invovles the passed image in the background calculation
        /// </summary>
        /// <param name="image">Image to be involved</param>
        public void AddImage(Bitmap image)
        {
            UnmanagedImage unmanagedImage = UnmanagedImage.FromManagedImage(image);
            for (int x = 0; x < _width; x++)
            {
                for (int y = 0; y < _height; y++) 
                {
                    _background[x, y].Red = (byte)((double)(_imageCount * _background[x, y].Red + unmanagedImage.GetPixel(x, y).R) / (double)(_imageCount + 1));
                    _background[x, y].Green = (byte)((double)(_imageCount * _background[x, y].Green + unmanagedImage.GetPixel(x, y).G) / (double)(_imageCount + 1));
                    _background[x, y].Blue = (byte)((double)(_imageCount * _background[x, y].Blue + unmanagedImage.GetPixel(x, y).B) / (double)(_imageCount + 1));
                }
            }
            _imageCount++;
        }
        /// <summary>
        /// Calculates the background using passed images
        /// </summary>
        /// <param name="images"></param>
        public void FromImages(List<Bitmap> images)
        {
            this.Clear();
            ColorD[,] temp = new ColorD[_width, _height];

            int count = images.Count;
            foreach (Bitmap image in images)
            {
                UnmanagedImage unmanagedImage = UnmanagedImage.FromManagedImage(image);
                for (int x = 0; x < _width; x++)
                {
                    for (int y = 0; y < _height; y++)
                    {
                        if (temp[x, y] == null) { temp[x, y] = new ColorD(); }

                        temp[x, y].R += (1d / (double)count) * (double)unmanagedImage.GetPixel(x, y).R;
                        temp[x, y].G += (1d / (double)count) * (double)unmanagedImage.GetPixel(x, y).G;
                        temp[x, y].B += (1d / (double)count) * (double)unmanagedImage.GetPixel(x, y).B;
                    }
                }
            }
            for (int x = 0; x < _width; x++)
            {
                for (int y = 0; y < _height; y++)
                {
                    _background[x, y].Red = (byte)temp[x, y].R;
                    _background[x, y].Green = (byte)temp[x, y].G;
                    _background[x, y].Blue = (byte)temp[x, y].B;
                }
            }

            _imageCount = count;
        }

        public UnmanagedImage EliminateBackground(Bitmap image)
        {
            UnmanagedImage unmangedImage = UnmanagedImage.FromManagedImage(image);
            EliminateBackground(unmangedImage);

            return unmangedImage;
        }

        public void EliminateBackground(UnmanagedImage unmangedImage)
        {
            for (int x = 0; x < unmangedImage.Width; x++)
            {
                for (int y = 0; y < unmangedImage.Height; y++)
                {
                    Color pixel = unmangedImage.GetPixel(x, y);
                    byte red = (byte)Math.Sqrt(Math.Pow(pixel.R, 2) - Math.Pow(_background[x, y].Red, 2));
                    byte green = (byte)Math.Sqrt(Math.Pow(pixel.G, 2) - Math.Pow(_background[x, y].Green, 2));
                    byte blue = (byte)Math.Sqrt(Math.Pow(pixel.B, 2) - Math.Pow(_background[x, y].Blue, 2));

                    unmangedImage.SetPixel(x, y, Color.FromArgb(red, green, blue));
                }
            }
        }
    }
}
